package june.sdsearchtest;
import java.io.File;
import java.util.ArrayList;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnKeyListener;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;

/**
 * sd카드 검색클래스. 어싱크테스크.
 * 기본구조로 프로그레스 다이얼로그를 포함한다.
 * 확장자 검색 전용으로 디자인.
 * 만약 일치문장 위주로 검색한다면 코드중에 end로 되어있는 부분을
 * 바꿔주워야 한다.
 * 검색결과를 어레이리스트로 반환한다.
 * @author HackJuneLee
 *
 */
public class SDsearchAsyncTesk extends AsyncTask<Integer, Integer, ArrayList<String[]>>{
	
	private Context c;
	private String extension;
	private Handler resultHandler;
	private ProgressDialog mProgress;
	private String MEDIA_PATH;
	private ArrayList<String[]> searchFile = new ArrayList<String[]>();
	private Boolean isSearchAct = true;
	
	/**
	 * 생성자에 컨텍스트와 검색할 확장자를 넣어주자.
	 * @param c 컨텍스트.
	 * @param extenstion 검색할 문장 확장자.
	 * @param h 결과를 반환하는 핸들러.
	 */
	public SDsearchAsyncTesk(Context c, String extenstion, Handler resultHandler) {
		this.c = c;
		this.extension = extenstion;
		this.resultHandler = resultHandler;
		//sd경로를 조회한다. 기종별 경로기 다른경우가 있음으로 /sdcard/가 맞다하더라도 바람직하지 않다.
        MEDIA_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
	}
	
	@Override
	protected void onPreExecute() {

		mProgress = new ProgressDialog(c);
		mProgress.setTitle("데이터 로딩"); 
		mProgress.setMessage("SD카드의 데이터를 검색중입니다. 검색어 : " + extension);
		mProgress.setIndeterminate(true);
		mProgress.setCancelable(true);
		mProgress.show();
		
		mProgress.setOnKeyListener(new OnKeyListener() {
			
			@Override
			public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
				// TODO Auto-generated method stub
				mLogShowing("keyListen : " + keyCode);
				if(keyCode == KeyEvent.KEYCODE_BACK){
					
					mLogShowing("뒤로가기가 눌렸다.");

					isSearchAct = false;
					
					Message cancellMessage = new Message();
					cancellMessage.arg1 = 101; //성공코드 100, 실패코드 101.
					resultHandler.sendMessage(cancellMessage);
				}
				return false;
			}
		});

		super.onPreExecute();
	}
	
	/**
	 * 백그라운드 작업. 작업종료후 테스크는 결과를 리턴한다.
	 */
	@Override
	protected ArrayList<String[]> doInBackground(Integer... params) {
		
		 //검색 가능한상태로 셋팅.
		isSearchAct = true;
		
		mUpdateList(MEDIA_PATH, c);
		return searchFile;
	}
	
	/**
	 * 다이얼로그를 종료하고 결과를 핸들러에 담아 원래있던 액티비티에 전달한다.
	 * 핸들러로 전달될 데이터는 오브잭트형으로 업캐스팅.
	 * 받는 핸들러는 다시 ArrayList<String[]>형으로 다운캐스팅을 해야한다.
	 */
	@Override
	protected void onPostExecute(ArrayList<String[]> result) {
		mLogShowing("post 호출");
		
		mProgress.dismiss();
		Message resultMsg = new Message();
		
		resultMsg.arg1 = 100; //성공코드 100. 실패코드 101.
		resultMsg.obj = (Object)result;
		resultHandler.sendMessage(resultMsg);
		
		super.onPostExecute(result);
	}
	
	/*
	//결과를 받아내는 핸들러 예제. execute를 호출한 클래스에 만들어놓고 테스크 생성자에 실어보내면 된다.
	Handler resultHandler = new Handler(){
    	@Override
    	public void handleMessage(Message msg) {
    		//성공일때 
    		if(msg.arg1 == 100){
    			ArrayList<String[]> result = (ArrayList<String[]>)msg.obj;
    			String[] searchfile = result.get(0);
    			//결과확인 제대로 됬다면 담겨있는 첫번째 결과값이 찍힌다
    			Log.e("june", "searchfile : " + searchfile[0] + ", " + searchfile[1]);
    			//리스트를 구성하든 뭘 하든 이제 이 아랫줄로. 
    		}
    		//실패일때 
    		else if(msg.arg1 == 101){
    			Log.e("june", "검색이 캔슬됨");
    		}
    	}
    };
    */
	
	/**
	 * 검색이 실패하거나 백키를 통해 취소했을경우 호출되는 함수.
	 * 핸들러에 실패코드인 101을 실어서 전달한다.
	 * 이에따른 처리는 액티비티 나름으로 해주면 된다.
	 * 
	 * ....이유는 모르지만 돌지않아. 왜인지 몰라. 배째.
	 * 그런고로 다이얼로그에 키 리스너를 달아서 back키가 눌릴경우만 상정하여
	 * 루프를 벗어나도록 코딩. 
	 */
	@Override
	protected void onCancelled() {
		
		mLogShowing("캔슬호출");
		
		//캔슬이 호출되면 검색이 불가능하도록 플래그를 변경한다. 이후 검색은 종료됨.
		isSearchAct = false;
		
		Message cancellMessage = new Message();
		cancellMessage.arg1 = 101; //성공코드 100, 실패코드 101.
		resultHandler.sendMessage(cancellMessage);
		
		super.onCancelled();
	}
	
	
	
	
	/**
     * sd카드를 검색한다. 기본방식은 재귀호출. 2차원 어레이리시트에 파일명과 파일패스를 담는다.
     */
    public void mUpdateList(String media_path, Context context) {
    	File home = new File(media_path); //검색을 진행할 홈루트.
    	File[] files = home.listFiles();
    	
    	if(files != null){
    		
    		for(int i = 0 ; i < files.length && isSearchAct ; i++){
    			 
    			if(files[i].isDirectory()){
    				
    				mUpdateList(files[i].getPath(), context);
//    				Log.i("aaa", "재귀호출. : " + files[i].getPath() + ", isSearchAct : " + isSearchAct);
    				 
    			} else {
    				
    				//확장자 검색시 아래 활성화.
    				if(files[i].getName().endsWith(extension)){
					//일치단어 검색시 아래 활성화.
					//if(files[i].getName().equals(extension)){
    					
    					//서피파일명과 파일패스를 add한다.
    					searchFile.add(new String[]{files[i].getName(), files[i].getPath()});	
    				}
    			}
    		}
    		
    	} else {
    		mLogShowing("검색결과 없음. or 검색종료.");
    	}
    }
    
    
    /**
     * 로그출력.
     * @param msg
     */
    public void mLogShowing(String msg){
    	Log.i("june", msg);
    }

}
